#include "Semaphore.h"
#include <errno.h>

using namespace std;

Semaphore :: Semaphore ( std::string nombre, char id,int valorInicial )
{
	this->valorInicial = valorInicial;

	key_t clave = ftok ( nombre.c_str(),id );

	if(clave < 0)
	{
//		cout <<errno<<endl;
		throw new std::exception;
	}

	this->id = semget ( clave,1,0666 | IPC_CREAT );

	if(this->id < 0)
		throw new std::exception;

	this->init ();
}

Semaphore::~Semaphore()
{
}

void Semaphore :: init ()
{
	semnum init;
	init.val = this->valorInicial;

	if(semctl ( this->id,0,SETVAL,init )<0)
		throw new std::exception;
}

void Semaphore :: dec ()
{
	struct sembuf operacion;

	operacion.sem_num = 0;	// numero de semaforo
	operacion.sem_op  = -1;	// restar 1 al semaforo
	operacion.sem_flg = SEM_UNDO;

	if(semop ( this->id,&operacion,1 )<0)
		throw new std::exception;
}

void Semaphore :: inc ()
{
	struct sembuf operacion;

	operacion.sem_num = 0;	// numero de semaforo
	operacion.sem_op  = 1;	// sumar 1 al semaforo
	operacion.sem_flg = SEM_UNDO;

	if(semop ( this->id,&operacion,1 ) <0)
		throw new std::exception;
}

bool Semaphore ::tryDec()
{
	bool retVal = true;
	semnum init;
	int result;

	if((result =semctl ( this->id,0,GETALL,init )) < 0)
	{
		cout << errno<<endl;
		throw new std::exception;
	}

	//Si el semaforo es 0, entonces no es posible decrementar
	//mas
	if(init.array[0] == 0)
		retVal = false;

	return retVal;
}

void Semaphore :: destroy ()
{
	if(semctl ( this->id,0,IPC_RMID ) < 0)
		cout <<"Error while deleting semaphore errno:" <<errno<<endl;
}
